﻿/** \file
* \$Rev: 184 $
* 
* \$Date: 2010-04-14 07:18:41 +0000 (Wed, 14 Apr 2010) $
*
* \$URL: http://chorus-twitter.googlecode.com/svn/trunk/src/gui/Link.cs $
*/

using System;
using System.Collections.Generic;

namespace chorus.gui
{
	/// <summary>
	/// A base "link" class. This contains properties that describe where in a
	/// section of RTF text the link is located.
	/// </summary>
	public abstract class Link
	{
		/// <summary>The start index of the link in the RTF text.</summary>
		public readonly int start;
		/// <summary>The end index of the link in the RTF text.</summary>
		public readonly int end;
		/// <summary>The link text.</summary>
		protected string text;
		/// <summary>The length of the link text.</summary>
		public int Length { get { return end - start + 1; } }
		/// <summary>Whether the link needs formatting (default true).</summary>
		public virtual bool NeedsFormatting { get { return true; } }

		/// <summary>The constructor.</summary>
		/// <param name="start">The start index of the link in the RTF text.</param>
		/// <param name="end">The end index of the link in the RTF text.</param>
		/// <param name="text">The link text.</param>
		public Link(int start, int end, string text)
		{
			this.start = start;
			this.end = end;
			this.text = text;
		}

		/// <summary>Test an index to see if this link contains it.</summary>
		/// <param name="index">The index in the RTF text to test.</param>
		/// <returns>Whether this link contains that index.</returns>
		public bool Contains(int index)
		{
			return index >= start && index <= end;
		}

		/// <summary>The action performed when the link is clicked.</summary>
		public abstract void Click();
	}

	/// <summary>
	/// A base class to generate a list of links from an RTF string.
	/// </summary>
	public abstract class LinkGenerator
	{
		/// <summary>The static list of all link generators.</summary>
		static List<LinkGenerator> gens = new List<LinkGenerator>()
		{
			new UserLinkGenerator()
		};

		/// <summary>Get all links from all generators based on an RTF string.</summary>
		/// <param name="haystack">The RTF string from which links will be generated.</param>
		/// <returns>The generated links.</returns>
		public static List<Link> GenerateAllLinks(string haystack)
		{
			List<Link> links = new List<Link>();
			foreach (LinkGenerator gen in gens)
				gen.GenerateLinks(haystack, links);
			return links;
		}

		/// <summary>Populate a list of links from an RTF string.</summary>
		/// <param name="haystack">The RTF string.</param>
		/// <param name="linklist">The list to populate.</param>
		protected abstract void GenerateLinks(string haystack, List<Link> linklist);
	}

	/// <summary>
	/// A link based on a Twitter user name, usually preceded by a "@".
	/// </summary>
	public class UserLink : Link
	{
		/// <summary>The constructor.</summary>
		/// <param name="start">The start index of the link in the RTF text.</param>
		/// <param name="end">The end index of the link in the RTF text.</param>
		/// <param name="text">The link text.</param>
		public UserLink(int start, int end, string text) :
			base(start, end, text)
		{
		}

		/// <summary>The action performed when the link is clicked.</summary>
		public override void Click()
		{
			twitter.user user;
			if (Program.users.byname.TryGetValue(text, out user))
				Deserialize(user);
			else
			{
				net.UserSource_Show usource = new net.UserSource_Show();
				usource.useridparms.screen_name.Val = text;
				usource.Auth = Program.accounts[0];
				usource.FetchAsync(Deserialize);
			}
		}

		/// <summary>The asynchronous deserialization callback.</summary>
		/// <param name="response">The received response object.</param>
		void Deserialize(twitter.user response)
		{
			if (response != null)
			{
				UserForm uform = new UserForm(response);
				uform.ShowDialog();
			}
		}
	}

	/// <summary>
	/// The class to generate user links from an RTF string.
	/// </summary>
	public class UserLinkGenerator : LinkGenerator
	{
		/// <summary>Populate a list of links from an RTF string.</summary>
		/// <param name="haystack">The RTF string.</param>
		/// <param name="links">The list to populate.</param>
		protected override void GenerateLinks(string haystack, List<Link> links)
		{
			for (int i = 0; i < haystack.Length; )
			{
				int linkindex = haystack.IndexOf('@', i);
				if (linkindex == -1)
					break;

				for (i = linkindex + 1; i < haystack.Length; i++)
					if (!twitter.user.ValidScreennameChar(haystack[i]))
						break;

				string screenname = haystack.Substring(linkindex + 1, i - linkindex - 1);
				links.Add(new UserLink(linkindex, i - 1, screenname));
			}
		}
	}
}
